#include "global.h"

#define KEYBOARD_PORT		0x60
#define KEYBOARD_ACK_PORT	0x61
#define ACK_BIT				0x80

#define KBD_BUFFER_SIZE		64
#define NUM_SCAN_CODES		105

/* Scan codes to ASCII for unshifted keys; unused keys are left out */
char charNoShift[NUM_SCAN_CODES] = { 
	0,033,'1','2','3','4','5','6','7','8','9','0','-','=','\b','\t',
	'q','w','e','r','t','y','u','i','o','p','[',']','\r',0,'a','s',
	'd','f','g','h','j','k','l',';',0,'`',0,'\\','z','x','c','v',
	'b','n','m',',','.','/',0,'*',0,' '       
};

/* Scan codes to ASCII for shifted keys; unused keys are left out */
char charWithShift[NUM_SCAN_CODES] = {
	0,033,'!','@','#','$','%','^','&','*','(',')','_','+','\b','\t',
	'Q','W','E','R','T','Y','U','I','O','P','{','}','\r',0,'A','S',
	'D','F','G','H','J','K','L',':',0,'~',0,'|','Z','X','C','V',
	'B','N','M','<','>','?',0,'*',0,' '  
};

int kbdDataReady;
char kbdData[KBD_BUFFER_SIZE];

void initializeKeyboardDriver()
{
	printf("  * Initializing keyboard driver... ");
	
	// Install the interrupt handler
	putWord((int)kbhandler, 0x0, 36);
	putWord(0x1000, 0x0, 38);
	
	// Initialize the driver variables
	kbdData[0] = '\0';
	kbdDataReady = 0;
	enable_irq(1);
	write_port(0x20, 0x20);
	
	printf("Done!\n");
}

// Interrupt handler that physically gets keys from the keyboard
void keyboardHandler()
{
	int scanCode = 0, value = 0, character = 0;
	
	// Get the key from the hardware
	scanCode = read_port(KEYBOARD_PORT);
	value = read_port(KEYBOARD_ACK_PORT);
		
	// Acknowledge the char was read
	write_port(KEYBOARD_ACK_PORT, value | ACK_BIT);
	write_port(KEYBOARD_ACK_PORT, value);
	
	if (!(scanCode & ACK_BIT))
	{
		kbdData[0] = charNoShift[scanCode];
		kbdDataReady = 1;
	}
	
	write_port(0x20, 0x20);
}

/*void kbdInsert(char c)
{
	mem_lock();
	kbdData[0] = c;
	kbdDataReady = 1;
	mem_unlock();
}*/

char getc()
{
	char key = '\0';
	
	// Enable interrupts just in case
	mem_unlock();
	
	while (kbdDataReady == 0);
	
	key = kbdData[0];
	
	mem_lock();
	kbdDataReady = 0;
	mem_unlock();
	
	return key;
}
